package cqrtplm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.hustcad.plm.basic.log.LogEventEnum;
import com.hustcad.plm.pdm.audit.util.TyplmAuditLogUtil;
import com.hustcad.plm.pdm.basedrule.dto.TyplmBaseRuleBoundedObjDTO;
import com.hustcad.plm.pdm.basedrule.service.TyplmBasedRuleService;
import com.hustcad.plm.pdm.classification.service.TyplmClassificationService;
import com.hustcad.plm.pdm.code.service.TyplmCodeService;
import com.hustcad.plm.pdm.common.model.dto.InsertClassificationType;
import com.hustcad.plm.pdm.common.util.CommonUtil;
import com.hustcad.plm.pdm.doc.constant.DocErrorCodeEnum;
import com.hustcad.plm.pdm.doc.dto.CreateDocInputDTO;
import com.hustcad.plm.pdm.doc.dto.DocDTO;
import com.hustcad.plm.pdm.doc.service.TyplmDocQueryService;
import com.hustcad.plm.pdm.doc.service.TyplmDocService;
import com.hustcad.plm.pdm.doc.service.impl.TyplmDocumentServiceImpl;
import com.hustcad.plm.pdm.doc.vo.DocumentVO;
import com.hustcad.plm.pdm.file.model.dto.FileGroupDTO;
import com.hustcad.plm.pdm.file.model.dto.FileMarkDTO;
import com.hustcad.plm.pdm.file.service.TyplmFileHandleService;
import com.hustcad.plm.pdm.iba.model.dto.IBASaveParamDTO;
import com.hustcad.plm.pdm.iba.service.TyplmCommonAttributeService;
import com.hustcad.plm.pdm.iba.service.TyplmReferenceValueService;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.doc.DocDO;
import com.ty.basic.entity.doc.DocMasterDO;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.entity.part.PartDO;
import com.ty.basic.handler.exceptionhandler.exception.TyException;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.mapper.RTPartMapper;
import cqrtplm.service.RTDocService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;

@Service
@Primary
@Slf4j
public class RTTyplmDocumentServiceImpl extends TyplmDocumentServiceImpl {

    @Resource
    private TyplmFileHandleService typlmFileHandleService;
    @Resource
    private TyplmCodeService typlmCodeService;
    @Resource
    private TyplmDocQueryService typlmDocQueryService;
    @Resource
    private TyplmDocService typlmDocService;
    @Resource
    private TyplmBasedRuleService typlmBasedRuleService;
    @Resource
    private TyplmReferenceValueService typlmReferenceValueService;
    @Resource
    private TyplmCommonAttributeService typlmCommonAttributeService;
    @Resource
    private TyplmClassificationService typlmClassificationService;
    @Resource
    private RTDocService docService;
    @Resource
    private RTPartMapper rtPartMapper;

    @Transactional(rollbackFor = Exception.class)
    public boolean batchAdd(FileGroupDTO fileGroupDto, CreateDocInputDTO dto) {
        List<MultipartFile> files = fileGroupDto.getFiles();
        String docType = dto.getDocType();
        List<String> list = new ArrayList<>();
        if(docType.contains("DesignDrawings")){
            for(MultipartFile multipartFile : files){
                String originalFilename = multipartFile.getOriginalFilename();
                String partNumber = null;
                if (originalFilename != null) {
                    partNumber = originalFilename.split("\\.")[0];
                }
                list.add(partNumber);
            }
            for(String partNumber :  list){
                String[] split = partNumber.split(",");
                for(int i = 0; i < split.length; i++){
                    PartDO partDO = rtPartMapper.queryLatestPartByNumberAndView(split[0], "Design", "RELEASED");//查询已发布版本
                    if(partDO == null){
                        throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("零部件在系统中不存在:" + split[0]);
                    }
                }
            }
        }
        DocDO docDO = this.insertDoc(dto);
        TyplmAuditLogUtil.info(Collections.singletonList(docDO), LogEventEnum.CRATE_OBJECT);
        updateDocIbaAttribute(docDO, dto);
        DocumentVO documentVO = queryDocByOid(docDO.getOid());
        if (CollUtil.isNotEmpty(list)) {
            docService.batchPartDescribeAndReferenceLink(documentVO, list);
        }
        return buildBatchCreatDocFile(fileGroupDto, docDO);
    }

    private boolean buildBatchCreatDocFile(FileGroupDTO fileGroupDto, DocDO docDO) {
        if (ObjectUtils.isNotEmpty(fileGroupDto)) {
            fileGroupDto.setDocId(docDO.getOid().toString());
            this.fileAssembly(fileGroupDto);
            try {
                log.info("开始文件上传");
                this.typlmFileHandleService.uploadDocFile(fileGroupDto, docDO.getOtype());
            } catch (TyException var4) {
                log.error("文件上传失败！", var4);
                throw DocErrorCodeEnum.FILE_UPLOAD_FAILED.getException(var4.getLocalizedMessage());
            }
        }

        return true;
    }

    private void fileAssembly(FileGroupDTO fileGroupDto) {
        List<FileMarkDTO> fileMarkDTOList = new ArrayList<>();
        List<MultipartFile> files = fileGroupDto.getFiles();
        if (CollUtil.isNotEmpty(files)) {
            MultipartFile file = files.get(0);
            FileMarkDTO fileMarkDTO = new FileMarkDTO();
            fileMarkDTO.setRoleKey("PRIMARY");
            fileMarkDTO.setParentFileId(null);
            fileMarkDTO.setFileName(file.getOriginalFilename());
            fileMarkDTOList.add(fileMarkDTO);
        }

        fileGroupDto.setFileMarkDTOList(fileMarkDTOList);
    }
    private DocDO insertDoc(CreateDocInputDTO createDocInputDTO) {
        HashMap<String, Object> codeChangeData = new HashMap<>();
        String docNumber = createDocInputDTO.getNumber();
        if (StringUtils.isEmpty(docNumber)) {
            docNumber = this.typlmBasedRuleService.getNumberByBaseRule(createDocInputDTO.getType(), createDocInputDTO.getContainerId(), createDocInputDTO.getContainerType());
            createDocInputDTO.setNumber(docNumber);
        }

        if (StringUtils.isEmpty(docNumber)) {
            TyplmBaseRuleBoundedObjDTO baseRuleBoundedObjDTO = this.typlmBasedRuleService.getBaseRuleBoundedObjInfo(new BigInteger(createDocInputDTO.getType()), new BigInteger(createDocInputDTO.getContainerId()), createDocInputDTO.getContainerType());
            if (ObjectUtil.isNotEmpty(baseRuleBoundedObjDTO)) {
                if (ObjectUtil.isNotEmpty(baseRuleBoundedObjDTO.getNumberType()) && baseRuleBoundedObjDTO.getNumberType().compareTo(1) == 0) {
                    IdentifierEntity classIdentifier = new IdentifierEntity();
                    classIdentifier.setOid(createDocInputDTO.getClassId());
                    classIdentifier.setOtype("ty.inteplm.type.CTyClassification");
                    docNumber = this.typlmCodeService.generateCode(classIdentifier, codeChangeData);
                }

                createDocInputDTO.setNumber(docNumber);
            }
        }

        List<DocMasterDO> docMasterDOList = this.typlmDocQueryService.queryDocMasterByDocNumber(createDocInputDTO.getNumber());
        if (CollUtil.isNotEmpty(docMasterDOList)) {
            throw DocErrorCodeEnum.DOC_NUMBER_ALREADY_EXIST.getException(createDocInputDTO.getNumber());
        } else {
            DocDTO docDTO = BeanUtil.copyProperties(createDocInputDTO, DocDTO.class);
            UserDO underUser = CommonUtil.getUser();
            String creator = Objects.nonNull(underUser) ? underUser.getName() : null;
            if (ObjectUtils.isNotEmpty(createDocInputDTO.getOwner())) {
                docDTO.setOwner(createDocInputDTO.getOwner());
            } else {
                docDTO.setOwner(creator);
            }

            docDTO.setPermissionsUserName(creator);
            docDTO.setSecuritiesKey(StringUtils.isEmpty(docDTO.getSecuritiesKey()) ? createDocInputDTO.getSecurity() : docDTO.getSecuritiesKey());
            DocDO result = this.typlmDocService.insertDoc(docDTO, creator);
            if (ObjectUtils.isNotEmpty(createDocInputDTO.getClassId())) {
                InsertClassificationType insertClassificationType = new InsertClassificationType();
                insertClassificationType.setObjId(result.getMasteredoid());
                insertClassificationType.setObjType(result.getMasteredotype());
                insertClassificationType.setClassificationId(createDocInputDTO.getClassId());
                insertClassificationType.setClassificationType("ty.inteplm.type.CTyClassification");
                this.typlmReferenceValueService.insertReferenceValueByObj(insertClassificationType.getClassificationId(), insertClassificationType.getClassificationType(), insertClassificationType.getObjId(), insertClassificationType.getObjType());
            }

            if (CollUtil.isNotEmpty(codeChangeData)) {
                this.typlmCodeService.saveCodeChangeData(codeChangeData);
            }

            return result;
        }
    }

    private void updateDocIbaAttribute(DocDO docDO,CreateDocInputDTO dto) {
        String docType = dto.getDocType();
        if (RTPlmConstant.DOC_WORK_INSTRUCTION.equals(docType)) {
            Map<String, List<String>> ibaAttr = new HashMap<>();
            String fileName = dto.getName();
            if (StringUtils.isEmpty(fileName)) {
                throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("文件命名错误，不可导入");
            }
            String[] split = fileName.split("_");
            if (split.length != 3) {
                throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("文件命名错误，不可导入");
            }
            ibaAttr.put(RTPlmConstant.DOC_IBA_MODEL_COLLECTION, Collections.singletonList(split[0]));
            ibaAttr.put(RTPlmConstant.DOC_IBA_PROCESS_NUMBER, Collections.singletonList(split[1]));
            ibaAttr.put(RTPlmConstant.DOC_IBA_PROCESS_NAME, Collections.singletonList(split[2]));
            BigInteger classificationOid = this.typlmClassificationService.getEntityClassificationOid(docDO);
            IBASaveParamDTO ibaSaveParamDTO = new IBASaveParamDTO();
            ibaSaveParamDTO.setIdentifier(docDO.getIdentifierRef());
            ibaSaveParamDTO.setIbaAttribute(ibaAttr);
            ibaSaveParamDTO.setCreat(Boolean.FALSE);
            ibaSaveParamDTO.setTypeoid(docDO.getTypeoid());
            ibaSaveParamDTO.setClassificationoid(classificationOid);
            typlmCommonAttributeService.saveAttributeValue(ibaSaveParamDTO);
        }
    }
}
